package com.google.code.mc4java.conn;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import com.google.code.mc4java.SaeMemcachexClient;
import com.google.code.mc4java.msg.Message;

public class NioConnection extends AbstractConnection {
    /**
     * CR.
     */
    public static final byte CR = (byte) '\r';


    /**
     * LF.
     */
    public static final byte LF = (byte) '\n';
    
	private SocketChannel socket;
	
	@Override
	public void init(SaeMemcachexClient.ServerInfo si) throws IOException {
		socket = SocketChannel.open();
		socket.socket().connect(new InetSocketAddress(si.getIp(),si.getPort()));
		socket.configureBlocking(false);
	}

	@Override
	public boolean send(Message msg) {
		ByteBuffer bb = ByteBuffer.allocate(msg.getMsg().length);
		bb.put(msg.getMsg());
		try {
			bb.flip();
			socket.write(bb);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public String readLine() {
		try {
			ByteBuffer bb = ByteBuffer.allocate(1);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while(true) {
				bb.clear();
				socket.read(bb);
				if(bb.get(0) == CR) {
					bb.clear();
					socket.read(bb);
					if(bb.get(0) == LF) {
						break;
					}
				}
				baos.write(bb.array());
			}
			String line = baos.toString();
			return line;
		} catch(Exception e) {
			e.printStackTrace();
			return "";
		}
	}
	
	@Override
	public byte[] receive(int len) {
		try {
			ByteBuffer bb = ByteBuffer.allocate(len);
			socket.read(bb);
			return bb.array();
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}		
	}

	public boolean skipEnter() {
		try {
			ByteBuffer b1 = ByteBuffer.allocate(1);
			socket.read(b1);
			if(b1.get(0) == CR) {
				b1.clear();
				socket.read(b1);
				if(b1.get(0) == LF) {
					return true;
				}
			}				
		} catch(Exception e) {
			e.printStackTrace();
		}
		return false;
	}
}
